<template>
  <main>
    Get TCP API:&nbsp;&nbsp;<a-select
      v-model:value="tcpAPIValue"
      :options="tcpAPIoptions"
      :field-names="{ label: 'label', value: 'api' }"
      size="middle"
      style="width: 200px"
    ></a-select>
    &nbsp;&nbsp;
    <a-button style="margin-left: 5px" @click="download('/filetcp/download')">
      TCP Download
    </a-button>
    <a-button style="margin-left: 5px" @click="eventSample"> TCP Event </a-button>
    <br /><br />

    <a-button style="margin-left: 5px" @click="axiosDownloadLargeData"> {{ btnLarge }} </a-button>
    <a-button style="margin-left: 5px" @click="fetchDownloadLargeData"> Fetch LargeData </a-button>
    <a-button style="margin-left: 5px" @click="download('/filerpc/download')">
      GRPC Download
    </a-button>
    <div style="margin-left: 80px">
      <textarea id="textarea_id" style="width: 100%; color: black" rows="10" :value="loginResponse">
      </textarea>
    </div>

    <input type="file" id="fileInput" />
    <a-button style="margin-left: 5px" @click="uploadAxios"> Upload Axios </a-button>
    <a-button style="margin-left: 5px" @click="uploadFetch"> Upload Fetch </a-button>
    <a-button style="margin-left: 5px" @click="uploadGRPC"> GRPC UPLOAD </a-button>
    <a-button style="margin-left: 5px" @click="uploadTCP"> TCP UPLOAD </a-button>
  </main>
</template>

<script setup lang="ts">
import { watch, ref, type Ref } from 'vue'
import type { SelectProps } from 'ant-design-vue'
import { type AxiosProgressEvent } from 'axios'
import { UploadEventType } from '@/api/CommonAPI'
import service, { BASE_URL } from '@/api/Request'
import type { DtoBase } from '@/api/APIModel'

//**********************  tcpAPI  *********************** SSSSSSSS*/
const tcpAPIValue = ref<string>()
watch(tcpAPIValue, async () => {
  console.log('tcpAPIValue', tcpAPIValue.value)
  for (let i = 0; i < tcpAPIoptions.value?.length; i++) {
    console.log('tcpAPIValue222', tcpAPIoptions.value[i].api, tcpAPIValue.value)
    if (tcpAPIoptions.value[i].api == tcpAPIValue.value) {
      let getAPI = '' + tcpAPIoptions.value[i].api
      if (tcpAPIoptions.value[i].param && tcpAPIoptions.value[i].param.length > 0) {
        getAPI = getAPI + '/' + tcpAPIoptions.value[i].param
      }
      console.log('tcpAPIValue333', tcpAPIoptions.value[i].api + '/' + tcpAPIoptions.value[i].param)
      loginResponse.value = JSON.stringify(await service.get(getAPI))
      console.log('tcpAPIValue result  ', loginResponse.value)
      break
    }
  }
})

const tcpAPIoptions = ref<{ api: number | string; label: string; param: string }[]>([
  { label: 'Hello', api: 'user/hello', param: 'test user1' },
  { label: 'Sum', api: 'user/sum', param: '' }
])
async function tcpAPI() {}
//**********************  tcpAPI  *********************** EEEEEEEEEE*/

const loginResponse = ref<string>('')
const btnLarge = ref<string>('Axios LargeData')
async function uploadFetch() {
  // 使用示例
  const fileInput = document.getElementById('fileInput') as HTMLInputElement
  const file = fileInput.files![0]
  const uploadUrl = BASE_URL + '/test/upload'
  let body: File | FormData = file

  body = new FormData()
  body.append('file', file)

  body.append('uploadKey', '987000')
  body.append('uploadType', UploadEventType.world + '')

  let response = await fetch(uploadUrl, {
    method: 'POST',
    body: body
  })
  if (!response || !response.ok || !response.body) {
    throw new Error('Network response was not ok')
  }

  let result = true
  let uploadedSize = 0
  const totalSize = file.size
  const reader = file.stream().getReader()
  while (result) {
    const { done, value } = await reader.read()
    if (value) {
      uploadedSize += value.length
    }

    const progress = (uploadedSize / totalSize) * 100
    console.log(`Upload progress: ${progress.toFixed(2)}%`)
    if (done) {
      result = false
      break
    }
  }
}
async function uploadTCP() {
  // 使用示例
  const fileInput = document.getElementById('fileInput') as HTMLInputElement
  const file = fileInput.files![0]
  const uploadUrl = '/filetcp/upload'
  const formData = new FormData()
  formData.append('file', file)
  // formData.append('key', '12345678')
  // formData.append('type', UploadEventType.Avator_Add + '')
  formData.append('uploadKey', '123uploadKey456')
  formData.append('uploadType', UploadEventType.Test + '')
  const result = await service.post(uploadUrl, formData, {
    // headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: (e: AxiosProgressEvent) => {
      const evt = e.event
      console.log('Upload progress:', evt.lengthComputable, evt.loaded, evt.total)
      if (evt.lengthComputable) {
        const percentComplete = (evt.loaded / evt.total) * 100
        console.log(`Upload progress: ${percentComplete.toFixed(2)}%`)
      }
    }
  })
  console.log('Upload formData:', result)
}
async function uploadGRPC() {
  // 使用示例
  const fileInput = document.getElementById('fileInput') as HTMLInputElement
  const file = fileInput.files![0]
  const uploadUrl = '/filerpc/upload'
  const formData = new FormData()
  formData.append('file', file)
  // formData.append('key', '12345678')
  // formData.append('type', UploadEventType.Avator_Add + '')
  formData.append('uploadKey', '123uploadKey456')
  formData.append('uploadType', UploadEventType.Test + '')
  const result = await service.post(uploadUrl, formData, {
    // headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: (e: AxiosProgressEvent) => {
      const evt = e.event
      console.log('Upload progress:', evt.lengthComputable, evt.loaded, evt.total)
      if (evt.lengthComputable) {
        const percentComplete = (evt.loaded / evt.total) * 100
        console.log(`Upload progress: ${percentComplete.toFixed(2)}%`)
      }
    }
  })
  console.log('Upload formData:', result)
}
async function uploadAxios() {
  // 使用示例
  const fileInput = document.getElementById('fileInput') as HTMLInputElement
  const file = fileInput.files![0]
  const uploadUrl = '/test/upload'
  const formData = new FormData()
  formData.append('file', file)
  // formData.append('key', '12345678')
  // formData.append('type', UploadEventType.Avator_Add + '')
  formData.append('key', '123456')
  formData.append('type', UploadEventType.Test + '')
  const result = await service.post(uploadUrl, formData, {
    // headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: (e: AxiosProgressEvent) => {
      const evt = e.event
      console.log('Upload progress:', evt.lengthComputable, evt.loaded, evt.total)
      if (evt.lengthComputable) {
        const percentComplete = (evt.loaded / evt.total) * 100
        console.log(`Upload progress: ${percentComplete.toFixed(2)}%`)
      }
    }
  })
  console.log('Upload formData:', result)
}

async function download(url: string = '/filerpc/download') {
  try {
    const res = await service.post(
      url,
      { downloadType: '3', downloadKey: 'dk123' },
      { responseType: 'blob' }
    )
    if (res.data instanceof Blob) {
      const blob = res.data
      const objectUrl = URL.createObjectURL(blob) //创建下载的链接
      const a = document.createElement('a')
      a.href = objectUrl
      let fileName = 'test.pdf'
      try {
        fileName = res.headers['content-disposition'].split('filename=')[1]
        fileName = decodeURI(fileName)
        console.log('download filename', fileName)
        a.download = fileName //设置文件名
        //下面这个写法兼容火狐
        a.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }))
      } catch (e) {
        console.error('content-disposition filename', e)
      } finally {
        window.URL.revokeObjectURL(objectUrl) //释放bolb对象
      }
      return { code: 0, message: '' } as DtoBase
    } else {
      return { code: -1, message: res.data } as DtoBase
    }

    // } else {
    //   return { code: 0, message: '' } as DtoBase
    // }
  } catch (error) {
    console.log('download API >>>>', error)
    return { code: -1, message: error + '' } as DtoBase
  }
}

async function eventSample() {
  try {
    const res = await service.post('/filetcp/eventSample')
    console.log('eventSample API >>>>', res)
    return { code: 0, message: '' } as DtoBase
  } catch (error) {
    console.log('eventSample API >>>>', error)
    return { code: -1, message: error + '' } as DtoBase
  }
}

async function axiosDownloadLargeData() {
  const textarea = document.getElementById('textarea_id')
  try {
    loginResponse.value = ''
    service.get('/test/largeData', {
      onDownloadProgress: (e: AxiosProgressEvent) => {
        //e.event.total如果为0需要服务端设置resp.set({ 'Content-Length': fileSizeInBytes })
        const req = e.event.currentTarget as XMLHttpRequest
        loginResponse.value = req.response
        // console.log('Download completed', e.event)
        const percentComplete = (e.event.loaded / e.event.total) * 100
        //   if (percentComplete === 100) {
        console.log(
          'Download completed',
          e.event.lengthComputable,
          e.event.loaded,
          e.event.total,
          percentComplete
        )
        btnLarge.value = Math.round(percentComplete) + '%'
        textarea!.scrollTop = textarea!.scrollHeight
        if (percentComplete >= 100) {
          btnLarge.value = 'Large Data'
        }
        if (e.event.lengthComputable) {
          //   }
        }
      }
    })
    // // const stream = new Readable({
    // //   encoding: undefined,
    // //   read(this: Readable, size: number) {}
    // // })
    // const token = window.localStorage.getItem('token')
    // const response = await axios.get('http://localhost:3000/fhc/test/largeData', {
    //   headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/octet-stream' },
    //   responseType: 'stream',
    //   timeout: 6000
    // })
    // const stream = response.data
    // stream.on('data', (data: Buffer) => {
    //   let _data = data.toString()
    //   console.log(_data)
    //   loginResponse.value = loginResponse.value + _data
    // })
    // stream.on('end', () => {
    //   console.log('stream done')
    // })
    // // .then((response) => {
    // //   // response.data.pipe(createWriteStream('test.txt'))
    // //   loginResponse.value = response.data.toString()
    // //   // response.data.on('data', (chunk: Buffer) => {
    // //   //   // logic to process stream data
    // //   //   console.log(chunk.toString())
    // //   //   loginResponse.value = chunk.toString() + '\r\n' + loginResponse.value
    // //   // })

    // //   // response.data.on('end', () => {
    // //   //   // logic for stream complete
    // //   //   console.log('   end   ')
    // //   // })
    // // })

    // // console.log(response.data)
    // // response.data.pipe(stream)
    // // stream.on('data', (chunk) => {
    // //   console.log(chunk.toString())
    // // })
    // // stream.on('close', () => {
    // //   console.log('   close   ')
    // // })
    // // stream.on('end', () => {
    // //   console.log('   end   ')
    // // })
    // // stream.on('error', (error) => {
    // //   console.log('   error   ', error)
    // // })
  } catch (error) {
    console.error(error)
  }
}

async function fetchDownloadLargeData() {
  try {
    loginResponse.value = ''
    // 在浏览器端，axios 是使用 XMLHttpRequest 对象来实现请求，设置 responseType: 'stream' 后会出现以下警告⚠️：
    // The provided value 'stream' is not a valid enum value of type XMLHttpRequestResponseType.
    // 所以，在浏览器端，我们需要使用浏览器内置API fetch 来实现 stream 流式请求。
    // 原文链接：https://blog.csdn.net/tiven_/article/details/132367904
    const downloadUrl = BASE_URL + '/test/largeData'
    let response = await fetch(downloadUrl)

    if (!response || !response.ok || !response.body) {
      throw new Error('Network response was not ok')
    }
    let totalLen = response.headers.get('Content-Length')

    const reader = response.body.getReader()
    const textDecoder = new TextDecoder()
    let result = true
    let doneLen = 0
    let mergedBuf = null
    while (result) {
      const { done, value } = await reader.read()
      if (value) {
        if (mergedBuf == null) {
          mergedBuf = value
        } else {
          // 创建一个新的Uint8Array来存储合并后的结果
          let merged: Uint8Array = new Uint8Array(mergedBuf.length + value.length)
          merged.set(mergedBuf, 0) // 从索引0开始设置u1
          merged.set(value, mergedBuf.length) // 从u1.length的位置开始设置u2
          mergedBuf = merged
        }
      }
      doneLen = doneLen + (value ? value.length : 0)
      console.log('Stream ended', done, totalLen, doneLen)
      if (done) {
        result = false
        break
      }
      const chunkText = textDecoder.decode(value)
      loginResponse.value = loginResponse.value + chunkText
    }

    saveUint8ArrayAsFile(mergedBuf!)
  } catch (e) {
    console.log(e)
  }
}

function saveUint8ArrayAsFile(array: Uint8Array) {
  // 将Uint8Array转换为Blob对象
  const blob = new Blob([array])

  // 创建一个指向Blob对象的URL
  const url = URL.createObjectURL(blob)

  // 创建一个a元素，用于触发下载
  const a = document.createElement('a')
  a.href = url
  a.download = 'test.txt'
  document.body.appendChild(a)
  a.click()

  // 清理并移除元素和对象URL
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
}
</script>
